Hexagonal Grid
https://gyazo.com/e597e94829abdf9e9fc547518c0226de
code:glsl
const float SIZE = 1.0;
const float SQRT3 = sqrt(3.0);
struct Hex {
vec2 cell;
vec2 coord;
vec2 id;
};
Hex findNearestHex(vec2 p) {
const mat2 MAT_SKEW = mat2(1.0, 1.0 / SQRT3, 0.0, 2.0 / SQRT3);
const mat2 INV_MAT_SKEW = mat2(1.0, -0.5, 0.0, SQRT3 / 2.0);
vec2 pt = p / SIZE * MAT_SKEW;
vec2 cell = floor(pt);
cell.y -= mod(cell.x + cell.y + 2.0, 3.0) - 1.0;
vec2 coord = pt - cell;
float isTopHalf = step(coord.x, coord.y);
cell += vec2(1.0 - isTopHalf, isTopHalf);
Hex hex;
hex.id = cell;
hex.coord = pt - cell;
hex.cell = cell * SIZE * INV_MAT_SKEW;
return hex;
}
解説
https://gyazo.com/8d3c9ba2450fb781e02586f263560ef4
code:glsl
vec2 pt = p / SIZE;
vec2 cell = floor( pt );
まず、とりあえずfloorでグリッドを作る
cellにはグリッド左下の座標が入る
https://gyazo.com/d5505c29c00c5adc6caad0acaaf193fd
code:glsl
cell.y += mod( 2.0 * cell.x - cell.y, 3.0 ) - 1.0;
1x3のグリッド
x方向の1単位ごとに、-y向きに1単位ずれる
cellがグリッドの (0, 1) という中途半端な位置になるが、これでいい
https://gyazo.com/e4e9b6333f1401aba5521387cd1f1fce
https://gyazo.com/e5d665eeddcff2b353ad6b7d834cc67b
code:glsl
vec2 coord = pt - cell;
float isTopHalf = step( coord.x, coord.y );
cell += vec2( 1.0 - isTopHalf, isTopHalf );
cell内における座標 coord を作り、cellに斜めに切り込みを入れる isTopHalf を定義
隣のcellと組み合わせると六角形が形成できるので、その六角形の真ん中へと cell を動かす
具体的には、上半分を1単位上に・下半分を1単位右に
https://gyazo.com/d729b1bffaa8dca7533eb316b71d6c17
code:glsl
const mat2 MAT_SKEW = mat2( 1.0, 1.0 / SQRT3, 0.0, 2.0 / SQRT3 );
const mat2 INV_MAT_SKEW = mat2( 1.0, -0.5, 0.0, SQRT3 / 2.0 );
vec2 pt = p / SIZE * MAT_SKEW;
// ...
hex.cell = cell * SIZE * INV_MAT_SKEW;
座標系に$ \begin{bmatrix} 1 & 0 \\ \frac{1}{\sqrt3} & \frac{2}{\sqrt3} \end{bmatrix}を掛けると、せん断して正六角形になる
出力を元の座標系で使いたい場合は、$ \begin{bmatrix} 1 & 0 \\ -0.5 & \frac{\sqrt3}{2} \end{bmatrix}で逆変換してやる
https://gyazo.com/ed12c99827c6b81318756d0cb0d0ab01
coord には、こんな感じでせん断したままのセル内の座標が収録されている
$ \max(|x|, |y|, |x-y|)を取ると、以下のような距離が得られるので、これを使って模様を描いたりしてもいいですね
https://gyazo.com/7a5f63305c95dfe4f1959d3c37807305
https://gyazo.com/e597e94829abdf9e9fc547518c0226de
適当に模様描いてみた sin( 40.0 * len )